package org.hdl.anima.fronent;

import org.hdl.anima.message.ErrorResponse;
import org.hdl.anima.message.IRequest;
import org.hdl.anima.message.IResponse;
import org.hdl.anima.message.ResponseCallback;
import org.hdl.anima.session.ISession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * 
 * @author qiuhd
 * @since  2014-2-18
 * @version V1.0.0
 */
public class DefaultResponseCallBack implements ResponseCallback {
	
	private final IRequest request;
	private final ISession session;
	private static final Logger logger = LoggerFactory.getLogger(DefaultResponseCallBack.class);
	
	private volatile boolean isDone = false;
	
	private Object lock = new Object();
	
	public DefaultResponseCallBack(IRequest request,ISession session) {
		this.request = request;
		this.session = session;
	}
	
	@Override
	public void done(IResponse response) {
		if (request.isTwoWay()) {
			if (isDone) {
				throw new IllegalStateException("Response alreay done");
			}
			synchronized (lock) {
				if (response != null) {
					response.setRequest(request);
					try {
						session.send(response);
					}catch (Exception e) {
						try {
							session.send(new ErrorResponse("System error"));
						} catch (Exception e1) {
							//ignore
						}
						logger.error("Failed to done,Cause:"+e.getMessage(),e);
						throw new IllegalStateException("Failed to done,Cause:"+e.getMessage());
					}
				}
				isDone = true;
			}
		}
	}

	@Override
	public void caught(Throwable exception) {
		
		if (request.isTwoWay()) {
			if (isDone) {
				throw new IllegalStateException("Response alreay done");
			}
			synchronized (lock) {
				if (exception != null) {
					IResponse resp = new ErrorResponse(exception);
					resp.setRequest(request);
					try {
						session.send(resp);
					}catch (Exception e) {
						logger.error("Failed to caught,Cause:"+e.getMessage(),e);
						throw new IllegalStateException("Failed to caught,Cause:"+e.getMessage());
					}finally {
						isDone = true;
					}
				}
				isDone = true;
			}
		}
	}

	@Override
	public boolean isDone() {
		return this.isDone;
	}
}

